﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using IMCOM.Imagiality.Core;
using IMCOM.Imagiality.Core.Modeling;
using IMCOM.Imagiality.Phases.ModelBuildingPhase.Scanning;
using IMCOM.Imagiality.Phases.ModelBuildingPhase.Reconstruction;
namespace IMCOM.Imagiality.Phases.ModelBuildingPhase
{
    public abstract class ModelBuildingPhase : Phase
    {
        protected Scanner scanner;
        protected DisjointModel disjointModel;

        protected ConcreteModelProcessor concreteModelProcessor;
        protected DisjointModelProcessor disjointModelProcessor;
        
        protected ScanPositioningService positioningService;
        protected ReconstructionService reconstructionService;

        public ModelBuildingPhase(Scanner scanner, ConcreteModelProcessor concreteModelProcessor, DisjointModelProcessor disjointModelProcessor, ScanPositioningService positioningService, ReconstructionService reconstructionService)
        {
            this.scanner = scanner;
            this.concreteModelProcessor = concreteModelProcessor;
            this.positioningService = positioningService;
            this.reconstructionService = reconstructionService;
        }

        public override Boolean IsTerminal()
        {
            return false;
        }

        public override PhaseParameter Activate(PhaseParameter input)
        {
            disjointModel = new DisjointModel(positioningService);
            return Build(disjointModel);
        }

        protected ConcreteModelPhaseParameter Build(DisjointModel disjointModel)
        {
            while (MoreScansNeeded())
            {
                WaitForScan();
                ScanResult scanResult = scanner.Scan();
                disjointModel.Apply(scanResult);
            }

            // Process Disjoint Model
            disjointModel = disjointModelProcessor.Process(disjointModel);

            // Build Candidate Concrete Model
            ConcreteModel candidateModel = disjointModel.ToConcreteModel(reconstructionService);
            
            // Process Candidate Concrete Model
            ConcreteModel theModel = concreteModelProcessor.Process(candidateModel);
            
            return new ConcreteModelPhaseParameter(theModel);
     
        }

        public override PhaseParameter Rewind()
        {
            return Build(disjointModel);
        }


        protected abstract void WaitForScan();
        protected abstract Boolean MoreScansNeeded();
        
    }


 
}
